package me.kagura.aspect;

import me.kagura.JSONQuery;
import me.kagura.JsonResult;
import me.kagura.annotation.JSONBodyField;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

/**
 * Created by ZFang on 2017/11/22.
 */
@Order(-1)
@Component
@Aspect
public class AspectJSONBodyField {

    public static boolean isBlank(String str) {
        int strLen;
        if (str != null && (strLen = str.length()) != 0) {
            for (int i = 0; i < strLen; ++i) {
                if (!Character.isWhitespace(str.charAt(i))) {
                    return false;
                }
            }

            return true;
        } else {
            return true;
        }
    }

    @Around(value = "(@annotation(org.springframework.web.bind.annotation.RequestMapping) || @annotation(org.springframework.web.bind.annotation.PostMapping)) && args(..)")
    public Object Around(ProceedingJoinPoint joinPoint) throws Throwable {
        Signature signature = joinPoint.getSignature();

        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String bodyString = (String) request.getAttribute("jsonBodyString");
        if (bodyString == null) {
            return joinPoint.proceed();
        }
        Object[] args = JSONBodyField(signature, joinPoint, bodyString);

        return joinPoint.proceed(args);

    }

    private Object[] JSONBodyField(Signature signature, ProceedingJoinPoint joinPoint, String bodyString) {
        Object[] args = joinPoint.getArgs();
        try {
            MethodSignature methodSignature = (MethodSignature) signature;
            Method targetMethod = methodSignature.getMethod();
            Parameter[] parameters = targetMethod.getParameters();

            //对常见类型的解析封装
            JsonResult bodyJsonResult = JSONQuery.select(bodyString, null);
            String[] parameterNames = methodSignature.getParameterNames();
            for (int i = 0; i < parameters.length; i++) {
                Parameter parameter = parameters[i];
                JSONBodyField annotation = parameter.getAnnotation(JSONBodyField.class);
                if (annotation != null) {
                    String fieldName = isBlank(annotation.value()) ? parameterNames[i] : annotation.value();
                    if (parameter.getType().equals(String.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName).getAsString();
                    } else if (parameter.getType().equals(Integer.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName, Integer.class);
                    } else if (parameter.getType().equals(Double.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName, Double.class);
                    } else if (parameter.getType().equals(Float.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName, Float.class);
                    } else if (parameter.getType().equals(Long.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName, Long.class);
                    } else if (parameter.getType().equals(Character.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName, Character.class);
                    } else if (parameter.getType().equals(int.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName).getAsInt();
                    } else if (parameter.getType().equals(double.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName).getAsDouble();
                    } else if (parameter.getType().equals(float.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName).getAsFloat();
                    } else if (parameter.getType().equals(long.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName).getAsLong();
                    } else if (parameter.getType().equals(char.class)) {
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName).getAsCharacter();
                    } else {
                        //最终没匹配到类型则进行转换
                        args[i] = JSONQuery.select(bodyJsonResult, fieldName, parameter.getType());
                    }

                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return args;
    }
}